package com.stxx.stiot2.gateway;

import com.stxx.framwork.exception.ServiceException;
import com.stxx.stiot2.domain.Gateway;
import com.stxx.stiot2.event.dto.P2tMsg;
import com.stxx.stiot2.event.dto.T2pMsg;
import com.stxx.stiot2.gateway.face.GatewayServer;
import org.noear.solon.core.event.EventBus;
import org.smartboot.socket.transport.AioQuickServer;
import org.smartboot.socket.transport.AioSession;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public abstract class AbstractTcpServer implements GatewayServer {
    private Map<String, AioSession> sessionMap = new HashMap<>();
    AioQuickServer server;
    public void init(Gateway gateway){
        try {
            server = new AioQuickServer(gateway.getParams().getPort(), (ByteBuffer readBuffer, AioSession session) -> {
                byte[] bytes = new byte[readBuffer.remaining()];
                readBuffer.get(bytes);
                return new String(bytes, StandardCharsets.UTF_8);
            }, (AioSession session, String msg) -> {
                T2pMsg msg1 = this.receive(null,msg);
                if(msg1==null) return;
                sessionMap.put(msg1.getTerminalCode(), session);
                EventBus.publish(msg1);
            });;
            server.start();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void close(){
        sessionMap.forEach((key, value) -> {
            if(!value.isInvalid()){
                value.close();
            }
        });
        sessionMap.clear();
        sessionMap = null;
        server.shutdown();
        server = null;
    }

    public AioSession getSession(String terminalCode){
        if(!sessionMap.containsKey(terminalCode)){
            throw new RuntimeException("terminalCode not exist");
        }
        return sessionMap.get(terminalCode);
    }

    @Override
    public void send(String gatewayCode, String terminalCode, P2tMsg message) {

        AioSession session = getSession(terminalCode);
        if(session==null||session.isInvalid()){
            throw new ServiceException("会话已关闭");
        }
        byte[] b = message.getProperties().toString().getBytes(StandardCharsets.UTF_8);
        try {
            session.writeBuffer().write(b,0,b.length);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
